//
//  HSYBaseVideoPlayerController.m
//  高仿暴走斗图
//
//  Created by key on 16/6/20.
//  Copyright © 2016年 huangsongyao. All rights reserved.
//

#import "HSYBaseVideoPlayerController.h"
#import "HSYBaseVideoPlayerView.h"
#import "RACSignal+Timer.h"
#import <AVFoundation/AVFoundation.h>

#define ANIMATION_DURATION              0.5f
#define TIMER_INTERVAL                  0.1f
#define VIDEO_PLAYER_VIEW_SHOW_TIMES    10.0f
#define MIN_VALUE                       0.0f
#define MAX_VALUE                       1.0f

@interface HSYBaseVideoPlayerController ()<HSYBaseVideoPlayerViewDelegate, UIGestureRecognizerDelegate>

@property (nonatomic, strong) RACDisposable *disposable;
@property (nonatomic, assign) BOOL isFullscreenMode;
@property (nonatomic, assign) CGRect originFrame;
@property (nonatomic, strong, readonly) HSYBaseVideoPlayerView *playerView;
@property (nonatomic, assign) CGRect frame;
@property (nonatomic, assign) CGFloat maxValue;
@property (nonatomic, copy) void(^dimissCompleteBlock)();                                   //dismiss控制器完成后的block回调
@property (nonatomic, copy) void(^willTransformedSmallScreen)(NSNumber *state);             //大屏转成小屏
@property (nonatomic, copy) void(^willChangeToFullscreenMode)(NSNumber *state);             //小屏转成大屏
@property (nonatomic, copy) void(^currentPlayTime)(NSNumber *value);

@property (nonatomic, assign) BOOL playingLocationVideo;

@end


//*****************************************************动画*******************************************************//

@interface HSYBaseVideoPlayerController (Animation)

- (void)transformedIntoSmallScreen;

@end

@implementation HSYBaseVideoPlayerController (Animation)

#pragma mark - Dissmiss Controller

- (void)dismissPlayerController
{
    //停止视频播放
    [self stop];
    @weakify(self);
    [UIView animateWithDuration:self.fullDuration animations:^{
        
        @strongify(self);
        self.view.alpha = MIN_VALUE;
        
    } completion:^(BOOL finished) {
        
        @strongify(self);
        if (self.dimissCompleteBlock) {
            self.dimissCompleteBlock();
        }
        [self setStatusBarHidden:NO withAnaimtion:UIStatusBarAnimationFade];
    }];
    
}

#pragma mark - Transformed Controller

- (void)transformedIntoSmallScreen
{
    if (!self.isFullscreenMode) {
        return;
    }
    BOOL isFullScreen = NO;
    if (self.willTransformedSmallScreen) {
        self.willTransformedSmallScreen(@(isFullScreen));
    }
    @weakify(self);
    [UIView animateWithDuration:self.fullDuration animations:^{
        
        @strongify(self);
        [self.view setTransform:CGAffineTransformIdentity];
        self.frame = self.originFrame;
        self.playerView.frame = self.view.bounds;
        
    } completion:^(BOOL finished) {
        
        @strongify(self);
        self.isFullscreenMode = isFullScreen;
        [self setStatusBarHidden:NO withAnaimtion:UIStatusBarAnimationFade];
    }];
}

- (void)transformedIntoFullScreen:(UIInterfaceOrientation)orientation
{
    if (self.isFullscreenMode) {
        return;
    }
    CGFloat angle = M_PI_2;
    if (orientation == UIDeviceOrientationLandscapeLeft) {
        angle = -angle;
    }
    
    self.originFrame = self.view.frame;
    BOOL isFullScreen = YES;
    if (self.willChangeToFullscreenMode) {
        self.willChangeToFullscreenMode(@(isFullScreen));
    }
    @weakify(self);
    [UIView animateWithDuration:self.fullDuration animations:^{
        
        @strongify(self);
        self.frame = PLAYER_CONTROLLER_CHANGE_FRAME;
        self.playerView.frame = CGRectMake(MIN_VALUE, MIN_VALUE, IPHONE_HEIGHT, IPHONE_WIDTH);
        [self.view setTransform:CGAffineTransformMakeRotation(angle)];
        
    } completion:^(BOOL finished) {
        
        @strongify(self);
        self.isFullscreenMode = isFullScreen;
        [self setStatusBarHidden:YES withAnaimtion:UIStatusBarAnimationFade];
    }];
}

- (void)setStatusBarHidden:(BOOL)isHidden withAnaimtion:(UIStatusBarAnimation)animation
{
    [[UIApplication sharedApplication] setStatusBarHidden:isHidden withAnimation:animation];
}

- (NSTimeInterval)fullDuration
{
    return ANIMATION_DURATION;
}

@end


@implementation HSYBaseVideoPlayerController

#pragma mark - Init

- (instancetype)initWithFrame:(CGRect)frame contentUrlString:(NSString *)urlString;
{
    if (self = [super init]) {
        
        self.view.frame = frame;
        [self setup];
        self.urlString = urlString;
    }
    return self;
}

- (void)setup
{
    self.playingLocationVideo = NO;                                                 //播放的是否为本地视频，默认为否
    self.view.backgroundColor = [UIColor blackColor];                               //默认背景色为黑色
    self.controlStyle = MPMovieControlStyleNone;                                    //不显示默认的进度条
    self.repeatMode = MPMovieRepeatModeNone;                                        //不重复播放
    [self prepareToPlay];                                                           //缓存
    self.movieSourceType = MPMovieSourceTypeUnknown;
    
    self.maxValue = MIN_VALUE;
    NSDictionary *property = @{
                               
                               @(kVideoPlayerProgressPropertyTypeMinValue)      : @(0.0f),
                               @(kVideoPlayerProgressPropertyTypeMaxValue)      : @(self.duration),
                               @(kVideoPlayerProgressPropertyTypeProgessValue)  : @(0.0f),
                               @(kVideoPlayerProgressPropertyTypeMinTintColor)  : [UIColor whiteColor],
                               @(kVideoPlayerProgressPropertyTypeMaxTintColor)  : [[UIColor lightGrayColor] colorWithAlphaComponent:0.4],
                               @(kVideoPlayerProgressPropertyTypeThumbImage)    : [UIImage imageNamed:@"course_icon_point"],
                               
                               };
    @weakify(self);
    _playerView = [HSYBaseVideoPlayerView showVideoPlayerViewForProgressProperty:property frame:self.view.bounds didChangedValueBlock:^(NSNumber *value) {
        @strongify(self);
        [self updateCurrentPlayTimeByValue:value];
    } playVideoBlock:^(UIButton *button, CGFloat value) {
        @strongify(self);
        if (button.selected) {
            [self pause];
        } else {
            [self rac_progessDispose];
            [self play];
        }
    } scalingVideoBlock:^(UIButton *button) {
        @strongify(self);
        if (button.selected) {
            [self transformedIntoFullScreen:UIInterfaceOrientationLandscapeRight];
        } else {
            [self transformedIntoSmallScreen];
        }
    } didPanGestrueChangeValueBlock:^(NSNumber *value) {
        @strongify(self);
        [self updateCurrentPlayTime:value];
    }];
    self.playerView.delegate = self;
    [self.view addSubview:self.playerView];
    
    [self configObserver];                                                          //添加视频相关的监听
}

- (void)updateCurrentPlayTime:(NSNumber *)time
{
    [self setCurrentPlaybackTime:fabs([time doubleValue])];
}

- (void)updateCurrentPlayTimeByValue:(NSNumber *)value
{
    [self updateCurrentPlayTime:value];
    [self pause];
    [self.playerView updateVideoPlayState];
    [self rac_stopTimer];
}

#pragma mark - Cancel KVO

- (void)dealloc
{
    [self cancelObserver];
}

- (void)cancelObserver
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - KVO To Video && Screen Accelerometer

- (void)configObserver
{
    @weakify(self);
    //播放状态改变
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:MPMoviePlayerPlaybackStateDidChangeNotification object:nil] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNotification *notification) {
        @strongify(self);
        CGFloat duration = floor(self.maxValue);//floor(self.isPlayLocationVideo ? self.playableDuration : self.duration);
        CGFloat current = floor(self.currentPlaybackTime);
        if (current == duration && duration > MIN_VALUE) {
            //播放结束
            self.playerView.maxValue = duration;
            [self rac_stopTimer];
            [self pause];
            self.currentPlaybackTime = floor([@(MIN_VALUE) doubleValue]);
            [self.playerView updateVideoPlayState];
        } else {
    
        }
    }];
    
    //媒体网络加载状态改变
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:MPMoviePlayerLoadStateDidChangeNotification object:nil] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNotification *notification) {
        //开始播放
        @strongify(self);
        if (self.playbackState == MPMoviePlaybackStatePlaying) {
            if (self.maxValue == MIN_VALUE) {
                self.maxValue = self.maxVideoTimeInterval;
                self.playerView.maxValue = floor(self.maxValue);//floor(self.isPlayLocationVideo ? self.playableDuration : self.duration);
            }
            [self rac_progessDispose];          //进度计时器
            [self.playerView activityAnimationByIsStartAnimation:NO];
        } else if (self.playbackState == MPMoviePlaybackStateInterrupted) {
            //缓冲时卡住了，这时候开启菊花的运转模式。
            [self.playerView activityAnimationByIsStartAnimation:YES];
        }
    }];
    
    //视频显示状态改变
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:MPMoviePlayerReadyForDisplayDidChangeNotification object:nil] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNotification *notification) {
    }];
    
    //确认播放时长时间后
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:MPMovieDurationAvailableNotification object:nil] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNotification *notification) {
        @strongify(self);
        self.maxValue = self.maxVideoTimeInterval;
    }];
    
    //监听耳机插入和拔掉通知
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:AVAudioSessionRouteChangeNotification object:nil] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNotification *notification) {
        NSInteger routeChangeReason = [[notification.userInfo valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
        switch (routeChangeReason) {
            case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
                NSLog(@"---耳机插入");
                break;
                
            case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: {
                NSLog(@"---耳机拔出");
                // 拔掉耳机继续播放
                [self play];
            }
                break;
                
            case AVAudioSessionRouteChangeReasonCategoryChange:
                break;
                
            default:
                break;
        }
    }];
}

- (NSTimeInterval)maxVideoTimeInterval
{
    if (self.playingLocationVideo) {
        return self.playableDuration;
    } else {
        return self.duration;
    }
}

#pragma mark - Change Progess && RAC_Timer

- (void)rac_stopAllTimer
{
    [self rac_stopTimer];
}

- (void)rac_stopTimer
{
    if (self.disposable) {
        [self.disposable dispose];
        self.disposable = nil;
    }
}

- (void)rac_progessDispose
{
    [self rac_stopTimer];
    @weakify(self);
    self.disposable = [[[RACSignal timerSignalOneMinuteForInterval:TIMER_INTERVAL] deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate *date) {
        @strongify(self);
        [self didChangeProgessValue];
    }];
}

- (void)didChangeProgessValue
{
    if (!self.playerView) {
        return;
    }
    
    CGFloat currentTime = fabs(self.currentPlaybackTime);                           //floor(self.currentPlaybackTime);
    CGFloat duration = floor(self.maxValue);                                        //floor(self.isPlayLocationVideo ? self.playableDuration : self.duration);
    self.playerView.cacheProgess = floor(self.playableDuration / self.maxValue);    //floor(self.playableDuration / self.duration);
    [self.playerView setTimeLabelValues:currentTime totalTime:duration];
    if (self.currentPlayTime) {
        self.currentPlayTime(@(currentTime));
    }
}

#pragma mark - Setter

- (void)setFrame:(CGRect)frame
{
    self.view.frame = frame;
    self.playerView.frame = CGRectMake(MIN_VALUE, MIN_VALUE, frame.size.width, frame.size.height);
    [self.playerView updateConstraint];
}

- (void)setContentURL:(NSURL *)contentURL
{
    [self stop];
    self.movieSourceType = MPMovieSourceTypeUnknown;
    [super setContentURL:contentURL];
    [self play];
}

- (void)hiddenVideoView:(BOOL)isHidden
{
    if (!isHidden && self.playerView) {
        [self.playerView dispath_afterHideAnimation];
    }
}

- (void)contentUrlString:(NSString *)urlString
{
    _urlString = urlString;
    NSURL *url = nil;
    if ([urlString hasPrefix:@"http"]) {
        //播放在线视频
        url = [NSURL URLWithString:urlString];
    } else {
        //播放本地视频
        url = [NSURL fileURLWithPath:urlString];
    }
    self.contentURL = url;
}

#pragma mark - HSYBaseVideoPlayerViewDelegate

- (void)progessControlEventTouchEndedForValue:(NSNumber *)value
{
    [self updateCurrentPlayTime:value];
    [self rac_progessDispose];
    [self.playerView updateVideoStopState];
    [self play];
}

- (void)progessControlEventTouchBeganForSlider:(UISlider *)slider
{
    [self rac_stopTimer];
    [self.playerView updateVideoPlayState];
    [self pause];
}

@end


//*******************************************************调用*****************************************************//

@implementation HSYBaseVideoPlayerController (Show)

+ (HSYBaseVideoPlayerController *)showStremingPlayerControllerByVideoUrlString:(NSString *)urlString willTransformedSmallScreenBlock:(void(^)(NSNumber *value))willTransformBlock willChangeToFullscreenModeBlock:(void(^)(NSNumber *value))willChangeBlock dimissCompleteBlock:(void(^)())completedBlock currentPlayTimeBlock:(void(^)(NSNumber *value))currentTimeBlock
{
    CGRect rect = rect = CGRectMake(MIN_VALUE, MIN_VALUE, PLAYER_CONTROLLER_WIDTH, PLAYER_CONTROLLER_HEIGHT);
    HSYBaseVideoPlayerController *playerController = [[HSYBaseVideoPlayerController alloc] initWithFrame:rect contentUrlString:urlString];
    
    @weakify(playerController);
    playerController.willTransformedSmallScreen = ^(NSNumber *value) {
        if (willTransformBlock) {
            willTransformBlock(value);
        }
    };
    
    playerController.willChangeToFullscreenMode = ^(NSNumber *value) {
        if (willChangeBlock) {
            willChangeBlock(value);
        }
    };
    
    playerController.dimissCompleteBlock = ^(void) {
        @strongify(playerController);
        [playerController.view removeFromSuperview];
        if (completedBlock) {
            completedBlock();
        }
    };
    
    playerController.currentPlayTime = ^(NSNumber *value) {
        if (currentTimeBlock) {
            currentTimeBlock(value);
        }
    };
    return playerController;
}

@end




